<FormBlock
    label="{__('teams / invite-user' )}"
    help="{__('teams / invite-user / help' )}"
    success="{successMessage}"
    error="{errorMessage}"
>
    <div class="flex">
        <input
            type="text"
            bind:value="inviteeEmail"
            width="1px"
            placeholder="{__('teams / invite-user / eg' )}"
        />&nbsp;
        <DropdownListInput
            disabled="{!isValidEmail}"
            label="<i class='fa { currentAction.updatingUsers ? 'fa-spin fa-circle-o-notch' : 'fa-envelope' }'></i>&nbsp; { __('teams / invite' ) }"
            items="{inviteOptions}"
        />
    </div>
</FormBlock>

<script>
    /* globals teamSettingsInvite */
    import DropdownListInput from '@datawrapper/controls/DropdownListInput.html';
    import FormBlock from '@datawrapper/controls/FormBlock.html';
    import { post, get } from '@datawrapper/shared/httpReq';
    import { __ } from '@datawrapper/shared/l10n';
    import escapeHtml from '@datawrapper/shared/escapeHtml';

    export default {
        components: { DropdownListInput, FormBlock },
        data() {
            return {
                inviteeEmail: '',
                invitedEmail: '',
                currentAction: {
                    updatingUsers: false,
                    isComplete: false,
                    isError: false,
                    errorCode: null,
                    responseData: null,
                    type: '',
                    role: ''
                }
            };
        },
        computed: {
            successMessage({ invitedEmail, currentAction }) {
                const { isComplete, isError, type, role } = currentAction;
                if (!isComplete || isError) return;

                const message = __(`teams / invite-user / ${type} / success`);
                return message
                    .replace('$1', escapeHtml(invitedEmail))
                    .replace('$2', __(`teams / role / ${role}`));
            },
            errorMessage({ invitedEmail, currentAction }) {
                const { isComplete, isError, errorCode, responseData, type } = currentAction;
                if (!isComplete || !isError) return;

                // we only want to show specific error messages
                // if an error code is known to us,
                // otherwise we show a generic 'server error' message
                const errorType = [400, 401, 406].includes(errorCode) ? errorCode : 'other';
                const maxTeamInvites =
                    errorCode === 406 && responseData && responseData.maxTeamInvites
                        ? responseData.maxTeamInvites
                        : null;

                const message = __(`teams / invite-user / ${type} / error / ${errorType}`);
                return message.replace('$1', invitedEmail).replace('$2', maxTeamInvites);
            },
            isValidEmail({ inviteeEmail }) {
                return /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
                    inviteeEmail
                );
            },
            inviteOptions({
                isAdmin,
                isTeamOwner,
                isValidEmail,
                inviteeExistsLoading,
                inviteeExists
            }) {
                const options = [
                    {
                        label: `<i class="fa fa-envelope"></i> &nbsp;...${__(
                            'teams / role / member'
                        )}`,
                        disabled: !isValidEmail,
                        action() {
                            teamSettingsInvite.inviteUser('member');
                        }
                    },
                    {
                        label: `<i class="fa fa-envelope"></i> &nbsp;...${__(
                            'teams / role / admin'
                        )}`,
                        disabled: !isValidEmail,
                        action() {
                            teamSettingsInvite.inviteUser('admin');
                        }
                    }
                ];

                if (isAdmin || isTeamOwner) {
                    options.push({
                        label: `<i class="fa fa-envelope"></i> &nbsp;...${__(
                            'teams / role / owner'
                        )}`,
                        disabled: !isValidEmail,
                        action() {
                            teamSettingsInvite.inviteUser('owner');
                        }
                    });
                }

                if (isAdmin) {
                    options.push(
                        {
                            label: `<span class="red"><i class="fa ${
                                inviteeExistsLoading ? 'fa-spin fa-circle-o-notch' : 'fa-plus'
                            }"></i> &nbsp;${__('teams / add-as').replace(
                                '%s',
                                __('teams / role / member')
                            )}</span>`,
                            disabled: !inviteeExists,
                            action() {
                                teamSettingsInvite.addUser('member');
                            }
                        },
                        {
                            label: `<span class="red"><i class="fa ${
                                inviteeExistsLoading ? 'fa-spin fa-circle-o-notch' : 'fa-plus'
                            }"></i> &nbsp;${__('teams / add-as').replace(
                                '%s',
                                __('teams / role / admin')
                            )}</span>`,
                            disabled: !inviteeExists,
                            action() {
                                teamSettingsInvite.addUser('admin');
                            }
                        },
                        {
                            label: `<span class="red"><i class="fa ${
                                inviteeExistsLoading ? 'fa-spin fa-circle-o-notch' : 'fa-plus'
                            }"></i> &nbsp;${__('teams / add-as').replace(
                                '%s',
                                __('teams / role / owner')
                            )}</span>`,
                            disabled: !inviteeExists,
                            action() {
                                teamSettingsInvite.addUser('owner');
                            }
                        }
                    );
                }

                return options;
            }
        },
        helpers: { __ },
        methods: {
            async addUser(role) {
                const { inviteeExists, inviteeUserId } = this.get();
                if (!inviteeExists) return;

                this.set({ currentAction: { updatingUsers: true, isComplete: false } });

                const response = await post(`/v3/teams/${this.get().team.id}/members`, {
                    raw: true,
                    payload: {
                        userId: inviteeUserId,
                        role
                    }
                });

                const responseJSON = !response.ok ? await response.json() : null;

                const currentAction = {
                    updatingUsers: false,
                    isComplete: true,
                    isError: !response.ok,
                    errorCode: !response.ok ? response.status : null,
                    responseData: responseJSON && responseJSON.data ? responseJSON.data : null,
                    type: 'add',
                    role
                };

                this.set({ invitedEmail: this.get().inviteeEmail, currentAction });
                this.fire('updateUsers');
            },
            async inviteUser(role) {
                const { inviteeEmail } = this.get();

                this.set({ currentAction: { updatingUsers: true, isComplete: false } });

                const response = await post(`/v3/teams/${this.get().team.id}/invites`, {
                    raw: true,
                    payload: {
                        email: inviteeEmail,
                        role
                    }
                });

                const responseJSON = !response.ok ? await response.json() : null;

                const currentAction = {
                    updatingUsers: false,
                    isComplete: true,
                    isError: !response.ok,
                    errorCode: !response.ok ? response.status : null,
                    responseData: responseJSON && responseJSON.data ? responseJSON.data : null,
                    type: 'invite',
                    role
                };

                this.set({ invitedEmail: this.get().inviteeEmail, currentAction });
                this.fire('updateUsers');
            },
            async debounceCheckUser() {
                if (!this.get().isAdmin) return;

                window.clearTimeout(window.checkUser);
                this.set({ inviteeExistsLoading: true });
                window.checkUser = setTimeout(() => {
                    this.checkUser();
                }, 200);
            },
            async checkUser() {
                let { inviteeEmail } = this.get();
                const { isValidEmail } = this.get();
                if (!isValidEmail) {
                    this.set({ inviteeExistsLoading: false });
                    return;
                }

                const json = await get(`/v3/users?search=${encodeURIComponent(inviteeEmail)}`);

                this.set({ inviteeExistsLoading: false, inviteeExists: false });

                if (json.list.length > 0) {
                    inviteeEmail = this.get().inviteeEmail;
                    json.list.forEach(el => {
                        if (el.email.toLowerCase() === inviteeEmail.toLowerCase()) {
                            this.set({
                                inviteeExists: true,
                                inviteeUserId: el.id
                            });
                        }
                    });
                }
            }
        },
        oncreate() {
            window.teamSettingsInvite = this;
        },
        onstate({ changed }) {
            if (changed.inviteeEmail) {
                this.set({ inviteeExists: false });
                this.debounceCheckUser();
            }
        }
    };
</script>

<style type="text/css">
    .flex {
        display: flex;
    }
    .flex input {
        width: 100%;
    }
    :global(.base-drop-btn) {
        white-space: nowrap;
    }
    :global(span.red) {
        color: #c71e1d;
    }
</style>
